﻿#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//char* GetMemory(void)
//{
//	char p[] = "hello world";
//	return p;//返回栈空间地址的问题 如果返回了地址，str接收就是野指针
//	//在栈里边申请的局部变量或是数组 出作用域的话就会销毁 并不能返回
//}
//void Test(void)
//{
//	char* str = NULL;
//	str = GetMemory();
//	printf(str);
//}
//int main()
//{
//	Test();
//	return 0;
//}

//int* test()
//{
//	int n = 10;
//	return &n;
//}
//int main()
//{
//	int * p = test();
//	printf("%d\n", *p);
//	return 0;
//}

//
//void GetMemory(char** p, int num)
//{
//	*p = (char*)malloc(num);
//	//p是str的地址 那么*p就是str
//}
//void Test(void)
//{
//	char* str = NULL;
//	GetMemory(&str, 100);
//	strcpy(str, "hello");
//	printf(str);
//	//当我不用的时候，要进行free，否则会出现内存泄漏的问题
//	free(str);
//	str = NULL;
//}
//int main()
//{
//	Test();
//	return 0; 
//}

//void Test(void)
//{
//	char* str = (char*)malloc(100);
//	strcpy(str, "hello");
//	free(str);//在这free释放完内存，并没有置为空指针 所以str还在指向malloc开辟的动态内存空间位置的起始地址 只是说free完就没有了
//	//访问权限
//	//正确的做法 置为空指针，防止形成非法访问
//	str = NULL;
//	if (str != NULL)
//	{
//		strcpy(str, "world");//要让world\0覆盖hello\0，因为str没有访问权限了 会形成非法访问内存空间
//		printf(str);
//	}
//}
//int main()
//{
//	Test();
//	return 0;
//}

//柔性数组
//建立在结构体中，而且是最后一个成员 
// 并且最后一个成员是数组，数组并未指定大小
//这个数组才是柔性数组！
//struct S
//{
//	char c;
//	int n;
//	int arr[];//这个就是柔性数组成员
//};
////但是在有些编译器上 这个写法也是代表着没有给数组定义多少个元素
//struct S1
//{
//	char c;
//	int n;
//	int arr[0];//柔性数组
//};

//柔性数组的特点
//结构中的柔性数组成员前⾯必须⾄少⼀个其他成员。
//sizeof 返回的这种结构⼤⼩不包括柔性数组的内存。
//包含柔性数组成员的结构⽤malloc()函数进⾏内存的动态分配，并且分配的内存应该⼤于结构的⼤⼩，以适应柔性数组的预期⼤⼩。
//struct S
//{
//	int n;//4
//	int arr[];//这个数组的大小并不清楚
//};//这是一个包含柔性数组的结构体
//int main()
//{
//	//printf("%zd\n", sizeof(struct S));//4 不计算柔性数组的大小
//	//柔性数组开辟空间是使用malloc开辟的
//	//把包含柔性数组的结构体创建在堆上
//	//malloc(sizeof(struct S) + 5*sizeof(int));//sizeof(struct S)仅仅是计算n的大小 
//	//   +5*sizeof(int)是让这个柔性数组根据需要进行创建大小
//	//而开辟的空间是给n和arr使用的
//	//因为malloc返回的是地址 最好强制类型转换成struct S* 然后把这块地址给ps 让ps指向这块空间
//	 struct S * ps = (struct S *)malloc(sizeof(struct S) + 5 * sizeof(int));
//	 //                                         4                20
//	 //realloc函数可以调整这块内存的大小 使得这块数组变得柔性起来 
//
//	 if (ps == NULL)
//	 {
//		 perror("malloc");
//		 return 1;
//	 }
//	 ps->n = 100;
//	 int i = 0;
//	 for (i = 0; i < 5; i++)
//	 {
//		 ps->arr[i] = i;
//	 }
//	 //觉得空间不够的时候 可以调整空间
//	 struct S* ptr =(struct S*)realloc(ps,sizeof(struct S)+10* sizeof(int));
//	 if (ptr != NULL)
//	 {
//		 ps = ptr;
//	 }
//
//	 //释放回归内存
//	 free(ps);
//	 ps = NULL;
//	return 0;
//}

struct S
{
	int n;
	int* arr;

};
int main()
{
	struct S* ps=(struct S*)malloc(sizeof(struct S));
	if (ps == NULL)
	{
		return 1;
	}
	//在这arr是整型指针
	ps->arr =(int*) malloc(5 * sizeof(int));
	if (ps->arr == NULL)
	{
		return 1;
	}
	//创建成功的话 可以使用
	ps->n = 100;//ps是一个结构体指针
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		ps->arr[i] = i;
	}

	//调整数组大小
	int * ptr = (int *)realloc(ps->arr, 10 * sizeof(int));
	if (ptr != NULL)
	{
		ps->arr = ptr;
	}
	//使用
	//...
	//释放
	free(ps->arr);
	ps->arr = NULL;
	free(ps);
	ps = NULL;

	return 0;
}

//上边这两种方案 肯定是柔性数组方案更好 使用malloc一次 并且释放也就一次
//malloc开辟的空间次数越多，中间导致的内存碎片也就越多 利用率就越低